/*******************************************************************************
 * * Copyright 2012 Impetus Infotech.
 *  *
 *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  * you may not use this file except in compliance with the License.
 *  * You may obtain a copy of the License at
 *  *
 *  *      http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 ******************************************************************************/
package cn.ilikes.tools.nosql.jpa.metadatas.processor.processores;

import java.lang.reflect.Field;
import java.util.Arrays;

import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;

import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.JPASQLRunTimeException;
import cn.ilikes.tools.nosql.jpa.metadatas.EntityMetaData;
import cn.ilikes.tools.nosql.jpa.metadatas.elements.EntityFields;
import cn.ilikes.tools.nosql.jpa.metadatas.elements.Relation;
import cn.ilikes.tools.nosql.jpa.metadatas.processor.TableProcessor;
import cn.ilikes.tools.nosql.jpa.metadatas.processor.validators.EntityValidatorException;

/**
 * The Class ManyToOneRelationMetadataProcessor.
 * 
 * @author Amresh Singh
 */
public class ManyToOneRelationProcessor implements Processors {
	private static Logger logger = Loggerfactory.instance(ManyToOneRelationProcessor.class);

	@Override
	public void validators(Class<?> clazz, EntityMetaData metadata) throws EntityValidatorException {

	}

	@Override
	public void processors(Class<?> clazz, EntityMetaData metadata) throws ElementProcessorException {
		validators(clazz, metadata);
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {

			// taking field's type as foreign entity, ignoring "targetEntity"
			ManyToOne ann = field.getAnnotation(ManyToOne.class);
			if (ann == null)
				continue;
			if (Loggerfactory.isdebug(logger))
				Loggerfactory.info(logger, "processors   ManyToOne Relation to   Metadata   " + field.getName() + "  EntityMetadata " + metadata);

			Class<?> targetEntity = field.getType();

			Relation relation = new Relation(field, targetEntity, null, ann.fetch(), Arrays.asList(ann.cascade()), ann.optional(), null, // mappedBy is
					Relation.ForeignKey.MANY_TO_ONE);

			boolean isJoinedByFK = field.isAnnotationPresent(JoinColumn.class);
			boolean isJoinedByTable = field.isAnnotationPresent(JoinTable.class);

			if (isJoinedByFK) {
				JoinColumn joinColumnAnn = field.getAnnotation(JoinColumn.class);
				relation.setJoinColumnName(joinColumnAnn.name());
			} else if (isJoinedByTable) {
				//			JoinTableMetadata jtMetadata = new JoinTableMetadata(relationField);
				//
				//			relation.setRelatedViaJoinTable(true);
				//			relation.setJoinTableMetadata(jtMetadata);
				throw new JPASQLRunTimeException("this JoinTable is not work ! ");
			}
			if (Loggerfactory.isdebug(logger))
				Loggerfactory.info(logger, " EntityMetadata  " + metadata.getEntityClazz().getSimpleName() + "  ; " + field.getName() + "   ;  add Relation  : " + relation);
			EntityFields entityFields = (EntityFields) ((EntityMetaData) metadata).getEntityField(field.getName());
			entityFields.getjPAField().setRelation(relation);
			entityFields.setSave(true);
			TableProcessor.processorsRelationIndexColumn(entityFields, field, relation);
		}
	}

}
